import random
import sys
import os
import time
def generate_card_id() -> str:
    return str(random.randint(100000, 999999))

def lock_check(func):
    def wrapper(atm_instance, user, card: "Card"):
        if card.is_locked:
            print(">>> 该卡已被锁定，请先解锁！")
            return
        return func(atm_instance, user, card)
    return wrapper

class Card:
    def __init__(self, card_id: str, password: str, money: float):
        self.card_id = card_id
        self.password = password
        self.money = money
        self.is_locked = False
        self.wrong_pwd_times = 0

    def check_pwd(self, pwd: str) -> bool:
        if pwd == self.password:
            self.wrong_pwd_times = 0
            return True
        self.wrong_pwd_times += 1
        if self.wrong_pwd_times >= 3:
            self.is_locked = True
        return False

class User:
    def __init__(self, name: str, id_card: str, phone: str, card: Card):
        self.name = name
        self.id_card = id_card
        self.phone = phone
        self.card = card

class Bank:
    def __init__(self):
        self.users: dict[str, User] = {}
        self.admin_user = "admin"
        self.admin_pwd = "123"

    def card_exists(self, card_id: str) -> bool:
        return card_id in self.users
    def get_user_by_card(self, card_id: str) -> User | None:
        return self.users.get(card_id)

    def create_user(self, name: str, id_card: str, phone: str, money: float, password: str) -> str:
        if money < 0:
            raise ValueError("预存金额不能小于 0")
        card_id = generate_card_id()
        while card_id in self.users:
            card_id = generate_card_id()
        card = Card(card_id, password, money)
        user = User(name, id_card, phone, card)
        self.users[card_id] = user
        return card_id

    def query_money(self, card_id: str, password: str) -> float:
        user = self.get_user_by_card(card_id)
        if not user:
            raise ValueError("卡号不存在")
        if not user.card.check_pwd(password):
            raise ValueError(f"密码输入错误，已连错 {user.card.wrong_pwd_times} 次")
        return user.card.money

    def deposit(self, card_id: str, password: str, amount: float):
        if amount <= 0:
            raise ValueError("存款金额必须大于 0")
        user = self.get_user_by_card(card_id)
        if not user:
            raise ValueError("卡号不存在")
        if not user.card.check_pwd(password):
            raise ValueError(f"密码输入错误，已连错 {user.card.wrong_pwd_times} 次")
        user.card.money += amount

    def withdraw(self, card_id: str, password: str, amount: float):
        if amount <= 0:
            raise ValueError("取款金额必须大于 0")
        user = self.get_user_by_card(card_id)
        if not user:
            raise ValueError("卡号不存在")
        if not user.card.check_pwd(password):
            raise ValueError(f"密码输入错误，已连错 {user.card.wrong_pwd_times} 次")
        if amount > user.card.money:
            raise ValueError("余额不足")
        user.card.money -= amount

    def transfer(self, from_id: str, from_pwd: str, to_id: str, amount: float):
        if amount <= 0:
            raise ValueError("转账金额必须大于 0")
        from_user = self.get_user_by_card(from_id)
        to_user = self.get_user_by_card(to_id)
        if not from_user or not to_user:
            raise ValueError("转出或转入卡号不存在")
        if from_id == to_id:
            raise ValueError("转出与转入卡号不能相同")
        if not from_user.card.check_pwd(from_pwd):
            raise ValueError(f"转出卡密码错误，已连错 {from_user.card.wrong_pwd_times} 次")
        if amount > from_user.card.money:
            raise ValueError("转出卡余额不足")
        from_user.card.money -= amount
        to_user.card.money += amount

    def lock_card(self, card_id: str, password: str):
        user = self.get_user_by_card(card_id)
        if not user:
            raise ValueError("卡号不存在")
        if user.card.is_locked:
            raise ValueError("该卡已经是锁定状态")
        if not user.card.check_pwd(password):
            raise ValueError(f"密码输入错误，已连错 {user.card.wrong_pwd_times} 次")
        user.card.is_locked = True

    def unlock_card(self, card_id: str, password: str):
        user = self.get_user_by_card(card_id)
        if not user:
            raise ValueError("卡号不存在")
        if not user.card.is_locked:
            raise ValueError("该卡未锁定，无需解锁")
        if password != user.card.password:
            raise ValueError("解锁密码错误")
        user.card.is_locked = False
        user.card.wrong_pwd_times = 0

    def check_admin(self, user: str, pwd: str) -> bool:
        return user == self.admin_user and pwd == self.admin_pwd

class ATM:
    def __init__(self):
        self.bank = Bank()

    @staticmethod
    def welcome():
        print("\n".join([
            "*********************",
            "*                   *",
            "* 欢迎登录银行管理系统 *",
            "*                   *",
            "*********************"
        ]))
    @staticmethod
    def menu():
        print("\n".join([
            "*********************",
            "*  1.开户    2.查询  *",
            "*  3.取款    4.存款  *",
            "*  5.转账    6.锁定  *",
            "*  7.解锁    Q.退出  *",
            "*********************"
        ]))
    def start(self):
        self.welcome()
        for i in range(3):
            u = input("请输入管理员账户：").strip()
            p = input("请输入密码：").strip()
            if self.bank.check_admin(u, p):
                print("操作成功，请稍后······\n")
                time.sleep(1)
                break
            else:
                print("管理员账户或密码输入错误···")
        else:
            print("连续 3 次错误，系统退出！")
            sys.exit(0)
